namespace core {

    function MakeCmdIndex(cmdBuf: egret.ByteArray): number {
        return <number>(cmdBuf.bytes[0] * 255 + cmdBuf.bytes[1])
    }

    type MessageHandle<T> = (cmdBuf: T) => void;
    export interface IMessageHandleMgr {
        InitAll()
        RegisterEncodeDecode<T>(index: number, decode: (reader: (protobuf.Reader | Uint8Array), length?: number) => T, encode: (message: T, writer?: protobuf.Writer) => protobuf.Writer)
        RegisterHandle<T>(index: number, handler: MessageHandle<T>)
        Process(cmdBuf: egret.ByteArray)
        Pack<T>(index: number, cmd: T): egret.ByteArray
    }

    export class MessageHandleMgrBase implements IMessageHandleMgr {
        private _allHandle = {}
        private _allDecode = {}
        private _allEncode = {}

        public InitAll() {
        }

        public RegisterEncodeDecode<T>(index: number, decode: (reader: (protobuf.Reader | Uint8Array), length?: number) => T, encode: (message: T, writer?: protobuf.Writer) => protobuf.Writer) {
            this._allDecode[index] = function (buf: Uint8Array): T {
                return <T>decode(buf)
            }
            this._allEncode[index] = function (buf: T): Uint8Array {
                return <Uint8Array>(encode(buf).finish())
            }
        }
        public RegisterHandle<T>(index: number, handler: MessageHandle<T>) {
            this._allHandle[index] = handler

        }

        public Register<T>(index: number, decode: (reader: (protobuf.Reader | Uint8Array), length?: number) => T, encode: (message: T, writer?: protobuf.Writer) => protobuf.Writer, handler: MessageHandle<T>) {
            this._allHandle[index] = handler
            this._allDecode[index] = function (buf: Uint8Array): T {
                return <T>decode(buf)
            }
            this._allEncode[index] = function (buf: T): Uint8Array {
                return <Uint8Array>(encode(buf).finish())
            }
        }
        public Process(cmdBuf: egret.ByteArray) {
            let index = MakeCmdIndex(cmdBuf)
            let handler = this._allHandle[index]
            let foo = this._allDecode[index]
            if (handler) {
                let cmd = foo(new Uint8Array(cmdBuf.buffer, 2, cmdBuf.buffer.byteLength - 2))
                handler(cmd)
            } else {
                console.log("Process 未处理数据：" + index)
            }
        }
        public Pack<T>(index: number, cmd: T): egret.ByteArray {
            let foo = this._allEncode[index]
            if (foo) {
                let cmdBuf = foo(cmd)

                let buf = new Uint8Array(cmdBuf.length + 2)
                buf.set(cmdBuf, 2)
                buf[0] = index / 255
                buf[1] = index % 255
                return new egret.ByteArray(buf)
            } else {
                console.log("Pack 未处理数据：" + index)
            }
            return null
        }
    }
}